Skip to content

API/COMPAT: add pydatetime-style positional args to Timestamp constructor #12482

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 7 commits into from

Conversation

thejohnfreeman
Copy link
Contributor

If more tests are desired, please let me know where to put them. Same for the whatsnew entry. This is my first pull request for Pandas.

cc @jreback

cdef _TSObject ts
cdef _Timestamp ts_base

if offset is not None and type(offset) is int:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use is_integer_object(offset)

@jreback
Copy link
Contributor

jreback commented Feb 27, 2016

pls add a whatsnew entry.

any luck with accepting the kwargs as well? (or too complicated)

@jreback jreback added Datetime Datetime data dtype API Design labels Feb 27, 2016
@thejohnfreeman
Copy link
Contributor Author

Should the whatsnew go in for 18.1 or something else?

kwargs got too complicated. I wanted to reach a working version of positional parameters first before building kwargs on top of it. I will try out an idea this weekend.

@jreback
Copy link
Contributor

jreback commented Feb 27, 2016

you can put in 0.18.1; if you finish up before we release we can just move

@@ -22,6 +22,14 @@ New features
Enhancements
~~~~~~~~~~~~

- Timestamps accept positional parameters like `datetime.datetime`:

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

put Timestamp in double back-ticks

say: can now accept

put a link in for datetime.datetime back to the constructor (on the python documentation page)

@jorisvandenbossche do we have a nicer way of doing this (as opposed to a straight link), IIRC, sphinx allows us to use an intra-module link (like we do with numpy)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, you can just do :func:datetime.datetime`` and that will link to the standard library's method

@thejohnfreeman thejohnfreeman force-pushed the GH-10758 branch 2 times, most recently from 18afb8e to b745b7d Compare March 5, 2016 15:26
@jreback
Copy link
Contributor

jreback commented May 7, 2016

@thejohnfreeman can you rebase / update & move whatsnew to 0.18.2

@thejohnfreeman
Copy link
Contributor Author

Ok, I rebased. I have time this week to finish this patch. I wrote a longer comment asking a question, but I'll just go ahead and try the signature you gave above.

def __new__(cls,
        object ts_input, object offset=None, tz=None, unit=None,
        year=None, month=None, day=None,
        hour=None, minute=None, second=None, tzinfo=None):

# The parameter list folds together legacy parameter names (the first
# four) and positional parameter names from pydatetime (starting with
# `minute`).
#
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good, this is a nice way to do this.

@codecov-io
Copy link

codecov-io commented May 9, 2016

Current coverage is 84.12%

Merging #12482 into master will not change coverage

@@             master     #12482   diff @@
==========================================
  Files           138        138          
  Lines         50384      50384          
  Methods           0          0          
  Messages          0          0          
  Branches          0          0          
==========================================
  Hits          42382      42382          
  Misses         8002       8002          
  Partials          0          0          

Powered by Codecov. Last updated by 82f54bd...79d63d4

@jorisvandenbossche
Copy link
Member

@thejohnfreeman You will also need to update the Timestamp docstring

@jreback
Copy link
Contributor

jreback commented May 10, 2016

also I believe its trivial to close #11630 (or it might already be done). Add a test and should be straightforward.

@thejohnfreeman
Copy link
Contributor Author

Take a look at my attempt at supporting both positional and keyword arguments. I removed some tests for TypeError; it just means we are more permissive. I'll fix up the doc string and add the other requested tests tomorrow.

return Timestamp(datetime(year, month, day, hour or 0,
minute or 0, second or 0, microsecond or 0, tzinfo),
tz=tzinfo)
if is_integer_object(offset):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

elif

@jreback
Copy link
Contributor

jreback commented May 11, 2016

whoosh @thejohnfreeman nice constuctor now! yeah prob need some more tests.

@shoyer
Copy link
Member

shoyer commented May 11, 2016

Effectively, we are doing type dependent multiple dispatch here with the Timestamp constructor. To be honest, I'm not a big fan of adding multiple paths like this that do such different things with the arguments.

@jreback
Copy link
Contributor

jreback commented May 11, 2016

@shoyer that doesn't make any sense. Timestamp is a sub-class of datetime. It doesn't take the correct (positional, nor keyword args ATM). I don't see the problem here. Yes it also does a lot more, but that's exactly the point, it IS user friendly w/o be ambiguous.

@thejohnfreeman
Copy link
Contributor Author

I updated the docstring and added tests. I'm considering this a first draft submitted for approval. If it's approved, I'll squash the commits and we can wait for Travis.

@shoyer
Copy link
Member

shoyer commented May 12, 2016

What about deprecating passing a single object (string or datetime) to pd.Timestamp in favor of using pd.to_datetime? That way we could get back to only one constructor eventually.

It would not be the end of the world to add this alternate constructor but IMO it would not be a positive improvement to have both.

If to do do it, let's clearly document the two constructors at the top of the docstring for the class, e.g.,

Timestamp(ts_input, object_offset=None, tz=None, unit=None)
Timestamp(year, month, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]])

Timestamp is...

I think sphinx can process that correctly but we should double check.

@jreback
Copy link
Contributor

jreback commented May 12, 2016

@shoyer why would you blow up a very useful interface?

Timestamp('20130101') is such a useful feature and you want to DEPRECATE?

the entire point is to REDUCE mental effort here. The whole notion of a user having to choose alternate constructors (and I know we had this discussion w.r.t. RangeIndex) is completely bonkers to me.

Sure if things are ambiguous, then you have to choose. In this case it is wholly unambiguous, replicates the existing (python datetime.datetime API), and provides very useful parsing abilities, not to mention its very light weight.

@shoyer
Copy link
Member

shoyer commented May 12, 2016

Timestamp('20130101') is such a useful feature and you want to DEPRECATE?

I agree -- my proposal is not entirely serious. I do think we need to make hard choices like this to achieve reliable APIs.

the entire point is to REDUCE mental effort here. The whole notion of a user having to choose alternate constructors (and I know we had this discussion w.r.t. RangeIndex) is completely bonkers to me.

Just to prove I'm not crazy, here are some high lights from the first page of a Google search for "Python multiple constructors":
http://stackoverflow.com/questions/2164258/multiple-constructors-in-python
http://stackoverflow.com/questions/682504/what-is-a-clean-pythonic-way-to-have-multiple-constructors-in-python
http://www.erol.si/2016/01/python-and-multiple-constructors/
https://pythonconquerstheuniverse.wordpress.com/2010/03/17/multiple-constructors-in-a-python-class/ (read the comments)

I could go on, but you get the point.

You'll notice that the universal advice seems to be to skip the magic and use classmethods for alternate constructors instead of overloading __init__.

@kawochen
Copy link
Contributor

If we are to add more code paths in the constructor, is it possible to make the entry points more obvious by calling specific from_* methods inside __new__ or __init__? After reading the doc string I feel like it might become harder for a casual contributor like me to debug the code. But I think this can be remedied by making the intention of each code path more visible in the code.

@thejohnfreeman
Copy link
Contributor Author

Hi @kawochen, I too want to make the code paths understandable. I had added some comments to each new path to document its intention. Did they help clarify at all?

@thejohnfreeman
Copy link
Contributor Author

I keep getting lint errors in the automated check. It doesn't say what the error is, and running trace8 locally doesn't give me any indication either.

The command "ci/script.sh" exited with 1.
1.00s$ ci/lint.sh
inside ci/lint.sh
discarding /Users/travis/miniconda/envs/pandas/bin from PATH
prepending /Users/travis/miniconda/envs/pandas/bin to PATH
NOT Linting

Any ideas what I need to do to get Travis to pass?

@jreback
Copy link
Contributor

jreback commented May 13, 2016

it's not lint errors but a failed test

https://travis-ci.org/pydata/pandas/jobs/129782361

@thejohnfreeman
Copy link
Contributor Author

Ah, it expects Timestamp(None) to return Not a Time (NaT).

year : int
month : int
day : int
hour : int [optional]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these need to be: int, optional (of this form)

@jreback
Copy link
Contributor

jreback commented May 13, 2016

lgtm. @thejohnfreeman nice explanations in the comments. I think it is clear.

@jorisvandenbossche @shoyer

comments?

@jreback jreback added this to the 0.18.2 milestone May 13, 2016
@jreback
Copy link
Contributor

jreback commented May 13, 2016

@thejohnfreeman did you add the test for #11630 (e.g the repr expr from above)

# GH 11630
self.assertEqual(
repr(Timestamp(2015, 11, 12)),
repr(Timestamp('20151112')))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is the test for #11630, Github didn't do the best job linking it to your earlier comment.

@jreback jreback closed this in 72164a8 May 20, 2016
@jreback
Copy link
Contributor

jreback commented May 20, 2016

thanks @thejohnfreeman great PR!

@thejohnfreeman
Copy link
Contributor Author

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
API Design Datetime Datetime data dtype
Projects
None yet
Development

Successfully merging this pull request may close these issues.

API/COMPAT: add kw args to Timestamp constructor
6 participants